package com.ahdy.tool;

import lombok.extern.slf4j.Slf4j;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;

/**
 * 音频合并工具类
 * 处理MP3文件的合并，支持简单的字节级合并和基于帧的合并
 */
@Slf4j
public class AudioMergeUtils {

    // MP3帧头标识
    private static final byte[] MP3_FRAME_SYNC = {(byte) 0xFF, (byte) 0xFB};
    private static final byte[] MP3_FRAME_SYNC_ALT = {(byte) 0xFF, (byte) 0xFA};

    /**
     * 合并多个MP3音频片段（简单字节合并）
     * 适用于来自同一TTS服务的相同格式音频片段
     */
    public static String mergeAudioSimple(List<byte[]> audioSegments) {
        if (audioSegments.isEmpty()) {
            throw new IllegalArgumentException("音频片段列表不能为空");
        }

        if (audioSegments.size() == 1) {
            return Base64.getEncoder().encodeToString(audioSegments.get(0));
        }

        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            boolean firstSegment = true;

            for (byte[] segment : audioSegments) {
                if (segment.length == 0) {
                    continue;
                }

                if (firstSegment) {
                    // 第一个片段保留完整内容
                    outputStream.write(segment);
                    firstSegment = false;
                } else {
                    // 后续片段跳过ID3标签（如果存在）
                    byte[] cleanSegment = removeId3Tags(segment);
                    outputStream.write(cleanSegment);
                }
            }

            byte[] mergedAudio = outputStream.toByteArray();
            log.info("音频合并完成，总大小: {} bytes", mergedAudio.length);

            return Base64.getEncoder().encodeToString(mergedAudio);

        } catch (IOException e) {
            log.error("音频合并失败", e);
            throw new RuntimeException("音频合并失败", e);
        }
    }

    /**
     * 移除MP3文件的ID3标签
     */
    private static byte[] removeId3Tags(byte[] mp3Data) {
        if (mp3Data.length < 10) {
            return mp3Data;
        }

        // 检查ID3v2标签
        if (mp3Data[0] == 'I' && mp3Data[1] == 'D' && mp3Data[2] == '3') {
            // 计算ID3v2标签大小
            int tagSize = ((mp3Data[6] & 0x7F) << 21) |
                         ((mp3Data[7] & 0x7F) << 14) |
                         ((mp3Data[8] & 0x7F) << 7) |
                         (mp3Data[9] & 0x7F);

            int headerSize = 10;
            int totalTagSize = headerSize + tagSize;

            if (totalTagSize < mp3Data.length) {
                byte[] cleanData = new byte[mp3Data.length - totalTagSize];
                System.arraycopy(mp3Data, totalTagSize, cleanData, 0, cleanData.length);
                log.debug("移除ID3v2标签，大小: {} bytes", totalTagSize);
                return cleanData;
            }
        }

        return mp3Data;
    }

    /**
     * 基于MP3帧的智能合并（实验性）
     */
    public static String mergeAudioAdvanced(List<byte[]> audioSegments, Path tempDir) throws IOException {
        if (audioSegments.isEmpty()) {
            throw new IllegalArgumentException("音频片段列表不能为空");
        }

        if (audioSegments.size() == 1) {
            return Base64.getEncoder().encodeToString(audioSegments.get(0));
        }

        List<byte[]> frames = new ArrayList<>();

        // 提取所有音频帧
        for (int i = 0; i < audioSegments.size(); i++) {
            byte[] segment = audioSegments.get(i);
            List<byte[]> segmentFrames = extractMp3Frames(segment);

            if (i == 0) {
                // 第一个片段保留所有帧
                frames.addAll(segmentFrames);
            } else {
                // 后续片段跳过第一帧（可能包含静音）
                if (segmentFrames.size() > 1) {
                    frames.addAll(segmentFrames.subList(1, segmentFrames.size()));
                } else if (!segmentFrames.isEmpty()) {
                    frames.addAll(segmentFrames);
                }
            }
        }

        // 重建MP3文件
        byte[] mergedAudio = rebuildMp3FromFrames(frames);

        log.info("高级音频合并完成，提取帧数: {}，最终大小: {} bytes", frames.size(), mergedAudio.length);

        return Base64.getEncoder().encodeToString(mergedAudio);
    }

    /**
     * 提取MP3帧
     */
    private static List<byte[]> extractMp3Frames(byte[] mp3Data) {
        List<byte[]> frames = new ArrayList<>();

        // 移除ID3标签
        byte[] cleanData = removeId3Tags(mp3Data);

        int offset = 0;
        while (offset < cleanData.length - 4) {
            // 查找帧同步字节
            if (isFrameSync(cleanData, offset)) {
                int frameSize = calculateFrameSize(cleanData, offset);

                if (frameSize > 0 && offset + frameSize <= cleanData.length) {
                    byte[] frame = new byte[frameSize];
                    System.arraycopy(cleanData, offset, frame, 0, frameSize);
                    frames.add(frame);
                    offset += frameSize;
                } else {
                    offset++;
                }
            } else {
                offset++;
            }
        }

        log.debug("从 {} bytes 数据中提取了 {} 个MP3帧", mp3Data.length, frames.size());
        return frames;
    }

    /**
     * 检查是否为帧同步字节
     */
    private static boolean isFrameSync(byte[] data, int offset) {
        if (offset + 1 >= data.length) {
            return false;
        }

        return (data[offset] == (byte) 0xFF &&
                (data[offset + 1] & 0xE0) == 0xE0);
    }

    /**
     * 计算MP3帧大小（简化版）
     */
    private static int calculateFrameSize(byte[] data, int offset) {
        if (offset + 3 >= data.length) {
            return 0;
        }

        // 这是一个简化的帧大小计算，实际MP3解析会更复杂
        // 对于来自同一TTS服务的音频，通常帧大小相对固定
        int header = ((data[offset] & 0xFF) << 24) |
                    ((data[offset + 1] & 0xFF) << 16) |
                    ((data[offset + 2] & 0xFF) << 8) |
                    (data[offset + 3] & 0xFF);

        // 提取比特率和采样率信息（简化）
        int bitrate = getBitrate(header);
        int sampleRate = getSampleRate(header);

        if (bitrate == 0 || sampleRate == 0) {
            return 144; // 默认帧大小
        }

        // 计算帧大小：(144 * bitrate / sampleRate) + padding
        int padding = (header >> 9) & 1;
        return (144 * bitrate / sampleRate) + padding;
    }

    /**
     * 从MP3头提取比特率
     */
    private static int getBitrate(int header) {
        int[] bitrateTable = {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0};
        int bitrateIndex = (header >> 12) & 0x0F;
        return bitrateIndex < bitrateTable.length ? bitrateTable[bitrateIndex] * 1000 : 128000;
    }

    /**
     * 从MP3头提取采样率
     */
    private static int getSampleRate(int header) {
        int[] sampleRateTable = {44100, 48000, 32000, 0};
        int sampleRateIndex = (header >> 10) & 0x03;
        return sampleRateIndex < sampleRateTable.length ? sampleRateTable[sampleRateIndex] : 44100;
    }

    /**
     * 从帧重建MP3文件
     */
    private static byte[] rebuildMp3FromFrames(List<byte[]> frames) throws IOException {
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            for (byte[] frame : frames) {
                outputStream.write(frame);
            }
            return outputStream.toByteArray();
        }
    }

    /**
     * 验证音频数据的完整性
     */
    public static boolean validateAudioData(byte[] audioData) {
        if (audioData == null || audioData.length < 4) {
            return false;
        }

        // 检查是否为有效的MP3文件
        // 方法1：检查ID3标签
        if (audioData.length >= 3 &&
            audioData[0] == 'I' && audioData[1] == 'D' && audioData[2] == '3') {
            return true;
        }

        // 方法2：检查MP3帧同步字节
        for (int i = 0; i < Math.min(audioData.length - 1, 1024); i++) {
            if (isFrameSync(audioData, i)) {
                return true;
            }
        }

        return false;
    }

    /**
     * 获取音频的基本信息
     */
    public static AudioInfo getAudioInfo(byte[] audioData) {
        AudioInfo info = new AudioInfo();

        if (audioData == null || audioData.length == 0) {
            return info;
        }

        info.setSize(audioData.length);
        info.setFormat("mp3");

        // 尝试提取更多信息
        byte[] cleanData = removeId3Tags(audioData);
        List<byte[]> frames = extractMp3Frames(cleanData);
        info.setFrameCount(frames.size());

        if (!frames.isEmpty()) {
            // 从第一帧提取信息
            byte[] firstFrame = frames.get(0);
            if (firstFrame.length >= 4) {
                int header = ((firstFrame[0] & 0xFF) << 24) |
                           ((firstFrame[1] & 0xFF) << 16) |
                           ((firstFrame[2] & 0xFF) << 8) |
                           (firstFrame[3] & 0xFF);

                info.setBitrate(getBitrate(header));
                info.setSampleRate(getSampleRate(header));
            }
        }

        return info;
    }

    /**
     * 音频信息类
     */
    public static class AudioInfo {
        private int size;
        private String format;
        private int frameCount;
        private int bitrate;
        private int sampleRate;

        // Getters and Setters
        public int getSize() { return size; }
        public void setSize(int size) { this.size = size; }

        public String getFormat() { return format; }
        public void setFormat(String format) { this.format = format; }

        public int getFrameCount() { return frameCount; }
        public void setFrameCount(int frameCount) { this.frameCount = frameCount; }

        public int getBitrate() { return bitrate; }
        public void setBitrate(int bitrate) { this.bitrate = bitrate; }

        public int getSampleRate() { return sampleRate; }
        public void setSampleRate(int sampleRate) { this.sampleRate = sampleRate; }

        @Override
        public String toString() {
            return String.format("AudioInfo{size=%d, format='%s', frames=%d, bitrate=%d, sampleRate=%d}",
                    size, format, frameCount, bitrate, sampleRate);
        }
    }
}
